/*
 * $Id: iptc.h 122 2011-04-13 15:24:20Z hyunghwan.chung $
 *
   Copyright 2005-2009 Chung, Hyung-Hwan.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an  BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

#ifndef _XP_LNX_IPTC_H_
#define _XP_LNX_IPTC_H_

#include <xp/types.h>
#include <xp/macros.h>
#include <xp/net/ether.h>

typedef struct xp_iptc_t xp_iptc_t;
typedef struct ipt_entry xp_iptc_entry_t;
typedef struct iptc_handle* xp_iptc_handle_t;

/* taken from linux/netfilter_ipv4/ip_tables.h
 * IPT_TABLE_MAXNAMELEN */
#define XP_IPTC_MAXTABLENAMELEN 32
/* IPT_FUNCTION_MAXNAMELEN */
#define XP_IPTC_MAXCHAINNAMELEN 30

struct xp_iptc_t
{
	xp_iptc_handle_t handle;
	xp_mchar_t       table[XP_IPTC_MAXTABLENAMELEN];
	xp_bool_t        loaded;

	xp_iptc_entry_t* entry;
	xp_size_t        entry_capacity;
	
	xp_bool_t        __dynamic;
};

enum xp_iptc_matip_flag_t
{
	XP_IPTC_MATIP_SRCIP    = (1u << 0),
	XP_IPTC_MATIP_DSTIP    = (1u << 1),
	XP_IPTC_MATIP_INIFCE   = (1u << 2),
	XP_IPTC_MATIP_OUTIFCE  = (1u << 3),
	XP_IPTC_MATIP_PROTO    = (1u << 4),
};

typedef enum xp_iptc_matip_flag_t xp_iptc_matip_flag_t;

struct xp_iptc_matip_t
{
	unsigned int invflags; /* can be ORed of xp_iptc_matip_flag_t */

	struct 
	{
		xp_uint32_t ip;
		xp_uint32_t mask;
	} src;

	struct 
	{
		xp_uint32_t ip;
		xp_uint32_t mask;
	} dst;

	const xp_char_t* inifce;
	const xp_char_t* outifce;

	xp_uint16_t proto;
};

typedef struct xp_iptc_matip_t xp_iptc_matip_t;

enum xp_iptc_matpro_flag_t
{
	XP_IPTC_MATPRO_SRCPORT  = (1u << 0),
	XP_IPTC_MATPRO_DSTPORT  = (1u << 1),
	XP_IPTC_MATPRO_ICMP     = (1u << 2),
};

typedef enum xp_iptc_matpro_flag_t xp_iptc_matpro_flag_t;

struct xp_iptc_matpro_t 
{
	unsigned int invflags; /* can be ORed of xp_iptc_matpro_flag_t */

	struct 
	{
		struct 
		{
			xp_uint16_t start;
			xp_uint16_t end;
		} src;

		struct 
		{
			xp_uint16_t start;
			xp_uint16_t end;
		} dst;
	} port;

	struct
	{
		xp_uint8_t type;    /* type to match */
		xp_uint8_t code[2]; /* range of code */
	} icmp;
};

typedef struct xp_iptc_matpro_t xp_iptc_matpro_t;

enum xp_iptc_matxtn_flag_t
{
	XP_IPTC_MATXTN_MAC        = (1u << 0),
	XP_IPTC_MATXTN_RATE       = (1u << 1),
	XP_IPTC_MATXTN_MARK       = (1u << 2),
	XP_IPTC_MATXTN_HASHLIMIT  = (1u << 3),
	XP_IPTC_MATXTN_CONNLIMIT  = (1u << 4),
	XP_IPTC_MATXTN_PHYSDEV    = (1u << 5),
	XP_IPTC_MATXTN_STATE      = (1u << 6)
};

enum xp_iptc_matxtn_hashlimit_mode_t
{
	XP_IPTC_MATXTN_HASHLIMIT_DSTIP   = 0x01,
	XP_IPTC_MATXTN_HASHLIMIT_DSTPORT = 0x02,
	XP_IPTC_MATXTN_HASHLIMIT_SRCIP   = 0x04,
	XP_IPTC_MATXTN_HASHLIMIT_SRCPORT = 0x08
};

typedef enum xp_iptc_matxtn_flag_t xp_iptc_matxtn_flag_t;

struct xp_iptc_matxtn_mark_t
{
	/* taken from kernel ipt_mask.h */
	xp_uint32_t value;
	xp_uint32_t mask;
};
typedef struct xp_iptc_matxtn_mark_t xp_iptc_matxtn_mark_t;

struct xp_iptc_matxtn_hashlimit_t
{
	xp_char_t name[32];

	xp_uint32_t mode;
	xp_uint32_t avg;
	xp_uint32_t burst;

	xp_uint32_t size;
	xp_uint32_t max;
	xp_uint32_t gcinterval;
	xp_uint32_t expire;
};
typedef struct xp_iptc_matxtn_hashlimit_t xp_iptc_matxtn_hashlimit_t;

struct xp_iptc_matxtn_connlimit_t
{
	unsigned int invert;
	unsigned int limit;
	unsigned int mask_pfxlen;
};
typedef struct xp_iptc_matxtn_connlimit_t xp_iptc_matxtn_connlimit_t;

enum xp_iptc_matxtn_physdev_flag_t
{
	XP_IPTC_MATXTN_PHYSDEV_IN         = (1u << 0),
	XP_IPTC_MATXTN_PHYSDEV_OUT        = (1u << 1),
	XP_IPTC_MATXTN_PHYSDEV_IS_IN      = (1u << 2),
	XP_IPTC_MATXTN_PHYSDEV_IS_OUT     = (1u << 3),
	XP_IPTC_MATXTN_PHYSDEV_IS_BRIDGED = (1u << 4)
};

struct xp_iptc_matxtn_physdev_t
{
	int flags;    /* bitwise-ORed of xp_iptc_matxtn_physdev_flag_t */
	int invflags; /* bitwise-ORed of xp_iptc_matxtn_physdev_flag_t */
 
	const xp_char_t* indev; /* used if XP_IPTC_MATXTN_PHYSDEV_IN is set */
	const xp_char_t* outdev; /* used if XP_IPTC_MATXTN_PHYSDEV_OUT is set */
};
typedef struct xp_iptc_matxtn_physdev_t xp_iptc_matxtn_physdev_t;


enum xp_iptc_matxtn_state_mask_t
{
	XP_IPTC_MATXTN_STATE_INVALID      = (1u << 0),
	XP_IPTC_MATXTN_STATE_NEW          = (1u << 1),
	XP_IPTC_MATXTN_STATE_ESTABLISHED  = (1u << 2),
	XP_IPTC_MATXTN_STATE_RELATED      = (1u << 3),
	XP_IPTC_MATXTN_STATE_UNTRACKED    = (1u << 4)
};

struct xp_iptc_matxtn_state_t
{
	unsigned int masks; /* bitwise-ORed of xp_iptc_matxn_state_mask_t */
};
typedef struct xp_iptc_matxtn_state_t xp_iptc_matxtn_state_t;


struct xp_iptc_matxtn_t
{
	unsigned int flags;    /* bitwise-ORed of xp_iptc_matxtn_flag_t */
	unsigned int invflags; /* bitwise-ORed of xp_iptc_matxtn_flag_t */
	
	struct
	{
		xp_byte_t src[XP_ETHER_LEN];
	} mac;

	struct
	{
		/* taken from kernel ipt_limit.h */
		xp_uint32_t avg;     /* average secs between packets * scale */
		xp_uint32_t burst;   /* period multiplier for upper limit */
	} rate;

	xp_iptc_matxtn_mark_t mark;
	xp_iptc_matxtn_hashlimit_t hashlimit;
	xp_iptc_matxtn_connlimit_t connlimit;
	xp_iptc_matxtn_physdev_t physdev;
	xp_iptc_matxtn_state_t state;
};

typedef struct xp_iptc_matxtn_t xp_iptc_matxtn_t;

enum xp_iptc_icmp_reject_t
{
	XP_IPTC_ICMP_REJECT_NET_UNREACHABLE,
	XP_IPTC_ICMP_REJECT_HOST_UNREACHABLE,
	XP_IPTC_ICMP_REJECT_PROTO_UNREACHABLE,
	XP_IPTC_ICMP_REJECT_PORT_UNREACHABLE,
	XP_IPTC_ICMP_REJECT_NET_PROHIBITED,
	XP_IPTC_ICMP_REJECT_HOST_PROHIBITED,
	XP_IPTC_ICMP_REJECT_ADMIN_PROHIBITED
};

typedef enum xp_iptc_icmp_reject_t xp_iptc_icmp_reject_t;

enum xp_iptc_tgtopt_mark_op_t
{
	XP_IPTC_TGTOPT_MARK_SET = 0,
	XP_IPTC_TGTOPT_MARK_AND,
	XP_IPTC_TGTOPT_MARK_OR
};

typedef enum xp_iptc_tgtopt_mark_op_t xp_iptc_tgtopt_mark_op_t;

union xp_iptc_tgtopt_t
{
	struct
	{
		struct
		{
			xp_uint16_t start;
			xp_uint16_t end;
		} port;	
	} redirect;

	struct
	{
		struct
		{
			xp_uint16_t start;
			xp_uint16_t end;
		} port;	
	} masquerade;

	struct
	{
		struct
		{
			xp_uint16_t start;
			xp_uint16_t end;
		} port;	
		struct
		{
			xp_uint32_t start;
			xp_uint32_t end;
		} ipaddr;
	} snat;

	struct
	{
		struct
		{
			xp_uint16_t start;
			xp_uint16_t end;
		} port;	
		struct
		{
			xp_uint32_t start;
			xp_uint32_t end;
		} ipaddr;
	} dnat;

	struct
	{
		xp_uint32_t value;
		xp_iptc_tgtopt_mark_op_t op;
	} mark;

	struct
	{
		xp_iptc_icmp_reject_t type;
	} reject;

	struct
	{
		xp_uint32_t priority;
	} classify;
};

typedef union xp_iptc_tgtopt_t xp_iptc_tgtopt_t;

#ifdef __cplusplus
extern "C" {
#endif

xp_iptc_t* xp_iptc_open (xp_iptc_t* iptc, const xp_char_t* table_name);
void xp_iptc_close (xp_iptc_t* iptc);
int xp_iptc_commit (xp_iptc_t* iptc);
void xp_iptc_abort (xp_iptc_t* iptc);
int xp_iptc_reset (xp_iptc_t* iptc);

void xp_iptc_set_changed (xp_iptc_t* iptc);

int xp_iptc_create_chain (xp_iptc_t* iptc, const xp_char_t* name);
int xp_iptc_delete_chain (xp_iptc_t* iptc, const xp_char_t* name);
int xp_iptc_zero_chain (xp_iptc_t* iptc, const xp_char_t* name);
int xp_iptc_flush_chain (xp_iptc_t* iptc, const xp_char_t* name);

int xp_iptc_walk_chain (
	xp_iptc_t* iptc,
	int (*func) (xp_iptc_t*, const xp_char_t*)
);

const xp_iptc_entry_t* xp_iptc_first_rule (
        xp_iptc_t* iptc, 
	const xp_char_t* name, 
	xp_iptc_entry_t const** rule_end
);

const xp_iptc_entry_t* xp_iptc_next_rule (
        xp_iptc_t* iptc, 
	const xp_iptc_entry_t* previous, 
	xp_iptc_entry_t const** rule_end
);

int xp_iptc_insert_entry (
	xp_iptc_t*              iptc,
	const xp_char_t*        chanam, /**< chain name */
	xp_size_t               pos,    /**< position */
	const xp_char_t*        tgtnam, /**< target name */
	const xp_iptc_matip_t*  matip,
	const xp_iptc_matpro_t* matpro,
	const xp_iptc_matxtn_t* matxtn,
	const xp_iptc_tgtopt_t* tgtopt
);

int xp_iptc_append_entry (
	xp_iptc_t*              iptc,   
	const xp_char_t*        chanam, /**< chain name */
	const xp_char_t*        tgtnam, /**< target name */
	const xp_iptc_matip_t*  matip,
	const xp_iptc_matpro_t* matpro,
	const xp_iptc_matxtn_t* matxtn,
	const xp_iptc_tgtopt_t* tgtopt
);

int xp_iptc_delete_entry (
	xp_iptc_t*              iptc,   
	const xp_char_t*        chanam, /**< chain name */
	const xp_char_t*        tgtnam, /**< target name */
	const xp_iptc_matip_t*  matip,
	const xp_iptc_matpro_t* matpro,
	const xp_iptc_matxtn_t* matxtn,
	const xp_iptc_tgtopt_t* tgtopt
);

int xp_iptc_delete_entry_at (
	xp_iptc_t*       iptc,
	const xp_char_t* chanam, /**< chain name */
	xp_size_t        pos     /**< position */
);


int xp_parseiptcmatxtnhashlimitavg (
        const xp_char_t* tok, 
	xp_size_t        len,
	xp_uint32_t*     val
);

#ifdef __cplusplus
}
#endif

#endif
